package com.ruoyi.web.controller.gd;

import java.io.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import cn.hutool.json.JSONObject;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.gd.fj.domain.bo.ZFujianBo;
import com.ruoyi.gd.fj.domain.vo.ZFujianVo;
import com.ruoyi.gd.fj.service.IZFujianService;
import com.ruoyi.gd.khxx.domain.vo.ZKhxxVo;
import com.ruoyi.gd.khxx.service.IZKhxxService;
import com.ruoyi.gd.ywdwgd.domain.vo.ZYwdwgdKfpVo;
import com.ruoyi.system.service.ISysDictTypeService;
import lombok.RequiredArgsConstructor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.gd.ywdwgd.domain.vo.ZYwdwgdVo;
import com.ruoyi.gd.ywdwgd.domain.bo.ZYwdwgdBo;
import com.ruoyi.gd.ywdwgd.service.IZYwdwgdService;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 业务完工单
 *
 * @author ruoyi
 * @date 2024-08-01
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/gd/ywdwgd")
public class ZYwdwgdController extends BaseController {

    private final IZYwdwgdService iZYwdwgdService;

    @Resource
    private final ISysDictTypeService dictTypeService;

    @Resource
    private IZFujianService fujianService;

    @Resource
    private IZKhxxService khxxService;

    @Value("${upload.path}")
    private String uploadPath;

    /**
     * 查询业务完工单列表
     */
    @SaCheckPermission("gd:ywdwgd:list")
    @GetMapping("/list")
    public TableDataInfo<ZYwdwgdVo> list(ZYwdwgdBo bo, PageQuery pageQuery) {
        return iZYwdwgdService.queryPageList(bo, pageQuery);
    }

    /**
     * 校验编号
     */
    @GetMapping("/verify/{bh}")
    public R<Boolean> verifyBh(@PathVariable("bh") String bh) {
        return R.ok(iZYwdwgdService.verifyBh(bh));
    }

    /**
     * 查询所有数据
     */
    @GetMapping("/listAllYwdwgd")
    public List<ZYwdwgdVo> listAllYwdwgd(ZYwdwgdBo bo) {
        List<ZYwdwgdVo> zYwdwgdVos = iZYwdwgdService.queryAllList(bo);
        return zYwdwgdVos;
    }

    /**
     * 导出业务完工单列表
     */
    @SaCheckPermission("gd:ywdwgd:export")
    @Log(title = "业务完工单", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(ZYwdwgdBo bo, HttpServletResponse response) {
        List<ZYwdwgdVo> list = iZYwdwgdService.queryList(bo);
        handleExportData(list);
        ExcelUtil.exportExcel(list, "业务单", ZYwdwgdVo.class, response);
    }

    private void handleExportData(List<ZYwdwgdVo> list) {
        // 获取字典数据是否已下场
        List<SysDictData> sfyxcList = dictTypeService.selectDictDataByType("gd_xczt_xbb");
        // 获取字典数据是否回款
        List<SysDictData> sfhkList = dictTypeService.selectDictDataByType("gd_sfhk");
        // 是否
        List<SysDictData> sfList = dictTypeService.selectDictDataByType("gd_sf");
        // 所属公司
        List<SysDictData> ssgsList = dictTypeService.selectDictDataByType("gd_ssgs");
        // 特殊处理
        List<SysDictData> tsclList = dictTypeService.selectDictDataByType("gd_tscl");
        // 到账账号
        List<SysDictData> dzzhList = dictTypeService.selectDictDataByType("gd_dzzh");
        for (int i = 0; i < list.size(); i++) {
            ZYwdwgdVo zYwdVo = list.get(i);
            // 设置编号
            zYwdVo.setExcelXh(i + 1);
            // 设置是否申请电子档，是否给客户电子档，纸质打印，已邮寄客户，是否开票，外包情况
            sfList.forEach(item -> {
                if (item.getDictValue().equals(zYwdVo.getSfsqdzd())) { // 是否申请电子档
                    zYwdVo.setSfsqdzd(item.getDictLabel());
                }
                if (item.getDictValue().equals(zYwdVo.getSfgkhdzd())) { // 是否给客户电子档
                    zYwdVo.setSfgkhdzd(item.getDictLabel());
                }
                if (item.getDictValue().equals(zYwdVo.getZzdy())) { // 纸质打印
                    zYwdVo.setZzdy(item.getDictLabel());
                }
                if (item.getDictValue().equals(zYwdVo.getYyjkh())) { // 已邮寄客户
                    zYwdVo.setYyjkh(item.getDictLabel());
                }
                if (item.getDictValue().equals(zYwdVo.getSfkp())) { // 是否开票
                    zYwdVo.setSfkp(item.getDictLabel());
                }
                if (item.getDictValue().equals(zYwdVo.getWbqk())) { // 外包情况
                    zYwdVo.setWbqk(item.getDictLabel());
                }
            });
            // 所属公司
            ssgsList.forEach(item -> {
                if (item.getDictValue().equals(zYwdVo.getSsgs())) {
                    zYwdVo.setSsgs(item.getDictLabel());
                }
            });
            // 检测方式
            if("1".equals(zYwdVo.getJcfs())) {
                zYwdVo.setJcfs("下场");
            }else if ("2".equals(zYwdVo.getJcfs())) {
                zYwdVo.setJcfs("送检");
            }
            // 特殊处理
            tsclList.forEach(item -> {
                if (item.getDictValue().equals(zYwdVo.getTscl())) {
                    zYwdVo.setTscl(item.getDictLabel());
                }
            });
            // 设置下场状态
            sfyxcList.forEach(item -> {
                if (item.getDictValue().equals(zYwdVo.getXczt())) {
                    zYwdVo.setXczt(item.getDictLabel());
                }
            });
            // 设置是否已回款
            sfhkList.forEach(item -> {
                if (item.getDictValue().equals(zYwdVo.getSfhk())) {
                    zYwdVo.setSfhk(item.getDictLabel());
                }
            });
            // 到账账号
            dzzhList.forEach(item -> {
                if (item.getDictValue().equals(zYwdVo.getDzzh())) {
                    zYwdVo.setDzzh(item.getDictLabel());
                }
            });
        }
    }

    /**
     * 导出选择数据
     */
    @Log(title = "业务单", businessType = BusinessType.EXPORT)
    @PostMapping("/exportSelectData/{ids}")
    public void exportSelectData(@PathVariable("ids") String ids, HttpServletResponse response) {
        List<ZYwdwgdVo> list = iZYwdwgdService.queryListByIds(ids);
        handleExportData(list);
        ExcelUtil.exportExcel(list, "业务单", ZYwdwgdVo.class, response);
    }

    /**
     * 导出开发票
     */
    @Log(title = "业务完工单导出开发票", businessType = BusinessType.EXPORT)
    @PostMapping("/exportKfp/{ids}")
    public byte[] exportKfp(@PathVariable("ids") String ids, HttpServletResponse response) {
        List<ZYwdwgdVo> list = iZYwdwgdService.queryListByIds(ids);
        List<ZYwdwgdKfpVo> kfpList =  handleExportKfp(list);
        return iZYwdwgdService.handleKfp(kfpList);
//        ExcelUtil.exportExcel(kfpList, "发票", ZYwdwgdKfpVo.class, response);
    }

    public List<ZYwdwgdKfpVo> handleExportKfp(List<ZYwdwgdVo> list) {
        List<ZYwdwgdKfpVo> kfpList = new ArrayList<>();
        int index = 1;
        for (int i = 0; i < list.size(); i++) {
            ZYwdwgdVo zYwdwgdVo = list.get(i);
            if (zYwdwgdVo != null && StringUtils.isNotEmpty(zYwdwgdVo.getKhid())) {
                ZYwdwgdKfpVo zYwdwgdKfpVo = new ZYwdwgdKfpVo();
                zYwdwgdKfpVo.setExcelXh(index);
                zYwdwgdKfpVo.setWgbh(zYwdwgdVo.getWgdh());
                zYwdwgdKfpVo.setKprq(zYwdwgdVo.getKprq());
                zYwdwgdKfpVo.setKpje(zYwdwgdVo.getKpje());
                zYwdwgdKfpVo.setBz(zYwdwgdVo.getBz());
                zYwdwgdKfpVo.setXzkpsj(zYwdwgdVo.getXzkpsj());
                ZKhxxVo zKhxx = khxxService.queryById(zYwdwgdVo.getKhid());
                if (zKhxx != null) {
                    zYwdwgdKfpVo.setKhname(zKhxx.getKhname());
                    zYwdwgdKfpVo.setKhsh(zKhxx.getSh());
                    if(StringUtils.isNotEmpty(zKhxx.getDh())) {
                        zYwdwgdKfpVo.setKpdzDh(zKhxx.getDz()+" " + zKhxx.getDh());
                    }else {
                        zYwdwgdKfpVo.setKpdzDh(zKhxx.getDz());
                    }
                    zYwdwgdKfpVo.setKhhzh(zKhxx.getXhkh());
                }
                kfpList.add(zYwdwgdKfpVo);
                index++;
            }
        }
        return kfpList;
    }

    /**
     * 获取业务完工单详细信息
     *
     * @param id 主键
     */
    @SaCheckPermission("gd:ywdwgd:query")
    @GetMapping("/{id}")
    public R<ZYwdwgdVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable String id) {
        return R.ok(iZYwdwgdService.queryById(id));
    }

    /**
     * 新增业务完工单
     */
    @SaCheckPermission("gd:ywdwgd:add")
    @Log(title = "业务完工单", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody ZYwdwgdBo bo) {
        return toAjax(iZYwdwgdService.insertByBo(bo));
    }

    /**
     * 修改业务完工单
     */
    @SaCheckPermission("gd:ywdwgd:edit")
    @Log(title = "业务完工单", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ZYwdwgdBo bo) {
        return toAjax(iZYwdwgdService.updateByBo(bo));
    }

    /**
     * 批量修改业务单状态
     */
    @PutMapping("/batchUpdateZt")
    public R<Boolean> batchUpdateZt(@RequestBody ZYwdwgdBo bo) {
        return R.ok(iZYwdwgdService.batchUpdateZt(bo));
    }

    /**
     * 删除业务完工单
     *
     * @param ids 主键串
     */
    @SaCheckPermission("gd:ywdwgd:remove")
    @Log(title = "业务完工单", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable String[] ids) {
        return toAjax(iZYwdwgdService.deleteWithValidByIds(Arrays.asList(ids), true));
    }

    /**
     * 查询业务完工单列表
     */
    @GetMapping("/resetDatabase")
    public void resetDatabase() {
        iZYwdwgdService.resetDatabase();
    }

    @GetMapping(value = "/downExcel/ywd", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void downExcelYwd(@RequestParam("ids") String ids,  HttpServletResponse response) throws IOException {
        // 获取数据
        List<ZYwdwgdVo> list = iZYwdwgdService.queryListByIds(ids);
        // 查询出来业务单，从业务单中获取所有的附件id
        List<String> collect = list.stream().map(item -> item.getBjdfj()).collect(Collectors.toList());
        // 通过附件id，将附件查询出来
        List<ZFujianVo> fjList = fujianService.queryListByIds(collect);

        // 创建一个字节数组输出流，用于收集压缩后的数据
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(baos);
        try{
            for (int i = 0; i < fjList.size(); i++) {
                ZFujianVo zFujianVo = fjList.get(i);
                File file = new File(uploadPath + zFujianVo.getFjpath());
                if (file.exists()) {
                    FileInputStream fileInputStream = new FileInputStream(file);
                    byte[] data = new byte[fileInputStream.available()];
                    // 将数据读取到数组中
                    fileInputStream.read(data);
                    // 设置压缩包栏目
                    zip.putNextEntry(new ZipEntry((i+1) +  "_" +zFujianVo.getFjname()));
                    // 将数据写入压缩包中
                    zip.write(data);
                    zip.flush();
                    zip.closeEntry();
                    fileInputStream.close();
                }
            }
            IOUtils.closeQuietly(zip);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        byte[] zipData = baos.toByteArray();
        exportData(response, zipData);
    }

    @GetMapping(value = "/downExcel/wgd", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void downExcelWgd(@RequestParam("ids") String ids,  HttpServletResponse response) throws IOException {
        // 获取数据
        List<ZYwdwgdVo> list = iZYwdwgdService.queryListByIds(ids);
        // 查询出来业务单，从业务单中获取所有的附件id
        List<String> collect = list.stream().map(item -> item.getWgdfj()).collect(Collectors.toList());
        // 通过附件id，将附件查询出来
        List<ZFujianVo> fjList = fujianService.queryListByIds(collect);

        // 创建一个字节数组输出流，用于收集压缩后的数据
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(baos);
        try{
            for (int i = 0; i < fjList.size(); i++) {
                ZFujianVo zFujianVo = fjList.get(i);
                File file = new File(uploadPath + zFujianVo.getFjpath());
                if (file.exists()) {
                    FileInputStream fileInputStream = new FileInputStream(file);
                    byte[] data = new byte[fileInputStream.available()];
                    // 将数据读取到数组中
                    fileInputStream.read(data);
                    // 设置压缩包栏目
                    zip.putNextEntry(new ZipEntry((i+1) +  "_" +zFujianVo.getFjname()));
                    // 将数据写入压缩包中
                    zip.write(data);
                    zip.flush();
                    zip.closeEntry();
                    fileInputStream.close();
                }
            }
            IOUtils.closeQuietly(zip);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        byte[] zipData = baos.toByteArray();
        exportData(response, zipData);
    }


    /**
     * 生成zip文件
     */
    private void exportData(HttpServletResponse response, byte[] data) throws IOException
    {
        response.reset();
//        response.addHeader("Access-Control-Allow-Origin", frontpath);
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With,X-App-Id, X-Token, Content-Disposition");
        response.setHeader("Content-Disposition", "attachment; filename=\"asp.zip\"");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");

        response.setHeader("Access-Control-Allow-Credentials", "true");

        IOUtils.write(data, response.getOutputStream());
    }

    /**
     * 获取业务完工单详细信息
     *
     * @param id 主键
     */
    @SaCheckPermission("gd:ywdwgd:query")
    @GetMapping("handleZt/{id}/{type}")
    public R<Boolean> handleZt(@PathVariable("id") String id, @PathVariable("type") String type) {
        int row = iZYwdwgdService.handleZt(id, type);
        return R.ok(row > 0);
    }

    /**
     * 生成报价单
     */
    @PostMapping("/genBjd")
    public R<ZFujianBo> genBjd(@RequestBody ZYwdwgdBo bo) {
        ZFujianBo zFujianBo = iZYwdwgdService.genBjd(bo);
        return R.ok(zFujianBo);
    }

    /**
     * 生成报价单
     */
    @PostMapping("/genBjdData")
    public byte[] genBjdData(@RequestBody ZFujianBo bo) {
        return iZYwdwgdService.genBjdData(bo);
    }

    /**
     * 生成电子档
     */
    @GetMapping("/genDzd")
    public byte[] genDzd(@RequestParam(name = "ids") String ids,
                         @RequestParam(name = "type") String type) {
        return iZYwdwgdService.genDzd(ids, type);
    }

    /**
     * 生成电子档New
     */
    @GetMapping("/genDzdNew")
    public byte[] genDzdNew(@RequestParam(name = "ids") String ids,
                         @RequestParam(name = "type") String type) {
        return iZYwdwgdService.genDzdNew(ids, type);
    }

    /**
     * 清洗为天津完工单
     */
    @GetMapping("/szWgdToTjWgd")
    public void szWgdToTjWgd(@RequestParam(name = "tjFjId") String tjFjId,
                                      @RequestParam(name = "wgrq") String wgrq,
                                       HttpServletResponse response) {
        List<ZFujianBo> fjList = iZYwdwgdService.szWgdToTjWgd(tjFjId, wgrq);
        try {
            // 判断当前是一个附件还是多个附件，如果是一个附件则将附件的流直接返回，如果是多个则将流返回
            if(fjList.size() == 1) {
                ZFujianBo zFujianBo = fjList.get(0);
                File file = new File(uploadPath + zFujianBo.getFjpath());
                if (file.exists()) {
                    byte[] bytes = fileToByteArray(file);
                    exportData(response, bytes);
                }
            }else if (fjList.size() > 1) {
                // 创建一个字节数组输出流，用于收集压缩后的数据
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ZipOutputStream zip = new ZipOutputStream(baos);
                for (ZFujianBo zFujianBo : fjList) {
                    File file = new File(uploadPath + zFujianBo.getFjpath());
                    if (file.exists()) {
                        FileInputStream fileInputStream = new FileInputStream(file);
                        byte[] data = new byte[fileInputStream.available()];
                        // 将数据读取到数组中
                        fileInputStream.read(data);
                        // 设置压缩包栏目
                        zip.putNextEntry(new ZipEntry(zFujianBo.getFjname()));
                        // 将数据写入压缩包中
                        zip.write(data);
                        zip.flush();
                        zip.closeEntry();
                        fileInputStream.close();
                    }
                }
                IOUtils.closeQuietly(zip);
                byte[] zipData = baos.toByteArray();
                exportData(response, zipData);
            }

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 清洗为天津完工单
     */
    @GetMapping("/clearBjd")
    public void clearBjd(@RequestParam(name = "fjId") String fjId,
                             HttpServletResponse response) {
        List<ZFujianBo> fjList = iZYwdwgdService.clearBjd(fjId);
        try {
            // 判断当前是一个附件还是多个附件，如果是一个附件则将附件的流直接返回，如果是多个则将流返回
            if(fjList.size() == 1) {
                ZFujianBo zFujianBo = fjList.get(0);
                File file = new File(uploadPath + zFujianBo.getFjpath());
                if (file.exists()) {
                    byte[] bytes = fileToByteArray(file);
                    exportData(response, bytes);
                }
            }else if (fjList.size() > 1) {
                // 创建一个字节数组输出流，用于收集压缩后的数据
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ZipOutputStream zip = new ZipOutputStream(baos);
                for (ZFujianBo zFujianBo : fjList) {
                    File file = new File(uploadPath + zFujianBo.getFjpath());
                    if (file.exists()) {
                        FileInputStream fileInputStream = new FileInputStream(file);
                        byte[] data = new byte[fileInputStream.available()];
                        // 将数据读取到数组中
                        fileInputStream.read(data);
                        // 设置压缩包栏目
                        zip.putNextEntry(new ZipEntry(zFujianBo.getFjname()));
                        // 将数据写入压缩包中
                        zip.write(data);
                        zip.flush();
                        zip.closeEntry();
                        fileInputStream.close();
                    }
                }
                IOUtils.closeQuietly(zip);
                byte[] zipData = baos.toByteArray();
                exportData(response, zipData);
            }

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public byte[] fileToByteArray(File file) throws IOException {
        byte[] byteArray = new byte[(int) file.length()];
        try (FileInputStream fis = new FileInputStream(file)) {
            fis.read(byteArray);
        }
        return byteArray;
    }


}
